<template>
  <div :class="classes || ''" class="bg-white-6 column no-wrap shadow-1 border-8 q-pa-md">
    <div class="row items-center">
      <div class="text-subtitle1 text-bold">{{ '设备运行时刻表' }}</div>
      <q-space></q-space>
    </div>
    <q-separator class="q-my-sm"></q-separator>
    <q-charts :emptyData="!rows.length" :loading="loading" :option="option"
              classes="col no-shadow no-padding"></q-charts>
  </div>
</template>

<script setup>
import { graphic } from 'echarts'
import { date } from 'quasar'
import { postAPI } from 'src/api'
import { adaptFontSize } from 'src/utils/utils.js'
import { computed, onMounted, ref } from 'vue'

defineProps({ classes: String })

const HEIGHT_RATIO = 20, DIM_CATEGORY_INDEX = 5, TASK_START_TIME = 2, TASK_END_TIME = 3
const _cartesianXBounds = [], _cartesianYBounds = []
const rows = ref([])
const cols = ref([])
const loading = ref(false)
const rowDimensions = computed(() => {
  return ['任务号', '任务等级', '预计时长']
})
const colDimensions = computed(() => {
  return ['任务号', '任务等级', '任务开始时间', '任务完成时间', '任务时长']
})
const option = computed(() => makeOption())

const makeOption = () => {
  const size10 = adaptFontSize(10)
  return {
    dataZoom: [{
      type: 'slider', xAxisIndex: 0, filterMode: 'weakFilter', height: size10 * 2, bottom: size10,
      show: cols.value.length > 20
    }, {
      type: 'slider', yAxisIndex: 0, filterMode: 'weakFilter', width: size10 * 2, right: size10, top: size10,
      bottom: size10 * 3.5, showDetail: false, show: rows.value.length > 20
    }],
    grid: {
      show: true, top: size10, bottom: size10 * 4, left: size10 * 20, right: size10 * 4, borderWidth: 0
    },
    xAxis: {
      type: 'time', position: 'top', splitNumber: 20, splitLine: { lineStyle: { color: ['#E9EDFF'] } },
      axisLine: { show: false }, axisTick: { show: false }, axisLabel: { color: '#929ABA', align: 'center' }
    },
    yAxis: {
      axisTick: { show: false }, splitLine: { show: false }, axisLine: { show: false },
      axisLabel: { show: false }, min: 0, max: rows.value.length
    },
    series: [{
      type: 'custom', renderItem: renderGanttItem, dimensions: colDimensions.value,
      encode: {
        x: [TASK_START_TIME, TASK_END_TIME], y: DIM_CATEGORY_INDEX, tooltip: [0, 1, TASK_START_TIME, TASK_END_TIME, 4]
      }, data: cols.value
    }, {
      type: 'custom', renderItem: renderAxisLabelItem, tooltip: { show: false }, silent: true,
      dimensions: rowDimensions.value, encode: { x: -1, y: 0 },
      data: rows.value.map((item, index) => [index].concat(item))
    }]
  }
}

const renderGanttItem = (params, api) => {
  const categoryIndex = api.value(DIM_CATEGORY_INDEX)
  const timeArrival = api.coord([api.value(TASK_START_TIME), categoryIndex])
  const timeDeparture = api.coord([api.value(TASK_END_TIME), categoryIndex])
  const coordSys = params.coordSys
  _cartesianXBounds[0] = coordSys.x
  _cartesianXBounds[1] = coordSys.x + coordSys.width
  _cartesianYBounds[0] = coordSys.y
  _cartesianYBounds[1] = coordSys.y + coordSys.height
  const barLength = timeDeparture[0] - timeArrival[0]
  const barHeight = HEIGHT_RATIO
  const x = timeArrival[0]
  const y = timeArrival[1] - barHeight
  const text = api.value(4) + ''
  const rectNormal = clipRectByRect(params, {
    x, y, width: barLength, height: barHeight
  })
  const rectVIP = clipRectByRect(params, {
    x, y, width: barLength / 2, height: barHeight
  })
  const rectText = clipRectByRect(params, {
    x, y, width: barLength, height: barHeight
  })
  const currentTime = Date.now()
  const val = cols.value[params.dataIndex][TASK_START_TIME]
  const fill = val > currentTime ? '#72B3FA' : '#0079FF'
  return {
    type: 'group',
    children: [{
      type: 'rect', ignore: !rectNormal, shape: rectNormal, style: { fill }
    }, {
      type: 'rect', ignore: !rectVIP, shape: rectVIP, style: { fill }
    }, {
      type: 'rect', ignore: !rectText, shape: rectText,
      style: { fill: 'transparent', stroke: 'transparent', text, textFill: '#fff', fontWeight: 'bold' }
    }]
  }
}

const renderAxisLabelItem = (params, api) => {
  const y = api.coord([0, api.value(0)])[1]
  if (y < params.coordSys.y + 15) return
  return {
    type: 'group', position: [10, y],
    children: [{
      type: 'rect',
      shape: { x: 0, y: -21, width: 180, height: 22, layout: 'cover' },
      style: { fill: '#F3F7F8' }
    }, {
      type: 'text',
      style: {
        x: 10, y: -3, fontSize: 14,
        text: `${api.value(1)}`,
        textVerticalAlign: 'bottom', textAlign: 'left', textFill: '#000'
      }
    }, {
      type: 'circle',
      shape: { cx: 58, cy: -10, r: 10, layout: 'cover' },
      style: { fill: 'rgba(255,140,0,0.51)', lineWidth: 2 }
    }, {
      type: 'text',
      style: {
        x: 53.5, y: -3, fontSize: 14,
        text: `${api.value(2)}`,
        textVerticalAlign: 'bottom', textAlign: 'left', textFill: '#000'
      }
    }, {
      type: 'text',
      style: {
        x: 76, y: -3, fontSize: 14,
        text: `预计时长: ${String(api.value(3)).padStart('0', 2) + ':00'}`,
        textVerticalAlign: 'bottom', textAlign: 'left', textFill: '#000'
      }
    }]
  }
}
const clipRectByRect = (params, rect) => {
  return graphic.clipRectByRect(rect, {
    x: params.coordSys.x, y: params.coordSys.y, width: params.coordSys.width, height: params.coordSys.height
  })
}
const initData = () => {
  loading.value = true
  const queryDate = date.formatDate(new Date(), 'YYYY-MM-DD')
  postAPI('/yfagv/api/mockTaskCallback/mockTaskQueues', { queryDate }, data => {
    const L = data.flightDatas?.length - 1 || 0
    cols.value = (data.flightDatas || []).map((el, index) => {
      el[2] = +el[2]
      el[3] = +el[3]
      el[4] = String(el[4]).padStart('0', 2) + ':00'
      el.push(L - index)
      return el
    })
    rows.value = (data.parkingApronDatas || []).reverse()
    loading.value = false
  }, () => (loading.value = false))
}
onMounted(initData)
</script>